package web.sms.mvc.service.impl;

import cn.palerock.core.shiro.useradmin.auditor.UserAuditor;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import web.sms.core.exception.AttributeCheckFailureException;
import web.sms.core.exception.ServiceException;
import web.sms.core.utils.MessageFormatter;
import web.sms.mvc.constant.UserConstant;
import web.sms.mvc.constant.WorkerOrderConstant;
import web.sms.mvc.dao.TaskAssignmentMapper;
import web.sms.mvc.dao.WorkOrderMapper;
import web.sms.mvc.dao.WorkerGroupMapper;
import web.sms.mvc.entity.*;
import web.sms.mvc.entity.pojo.WorkerCaptain;
import web.sms.mvc.service.RemindService;
import web.sms.mvc.service.TaskAssignmentService;
import web.sms.mvc.service.UserService;
import web.sms.utils.ObjectUtils;

import java.util.Date;
import java.util.List;

/**
 * 时间： 2017/12/23
 *
 * @author Eoly
 */
@Service
public class TaskAssignmentServiceImpl implements TaskAssignmentService {

    private final TaskAssignmentMapper taskAssignmentMapper;
    private final WorkerGroupMapper workerGroupMapper;
    private final WorkOrderMapper workOrderMapper;
    private final UserService userService;
    private final UserAuditor userAuditor;
    private final RemindService remindService;
    private final Logger logger = LoggerFactory.getLogger(TaskAssignmentServiceImpl.class);

    @Autowired
    public TaskAssignmentServiceImpl(TaskAssignmentMapper taskAssignmentMapper, WorkerGroupMapper workerGroupMapper, WorkOrderMapper workOrderMapper, UserService userService, UserAuditor userAuditor, RemindService remindService) {
        this.taskAssignmentMapper = taskAssignmentMapper;
        this.workerGroupMapper = workerGroupMapper;
        this.workOrderMapper = workOrderMapper;
        this.userService = userService;
        this.userAuditor = userAuditor;
        this.remindService = remindService;
    }

    @Override
    public void doDistributionTask(Integer taskId, Integer groupId) {
        // 检查权限
        userAuditor.checkPerms("order:admin|order:edit");
        TaskAssignment taskAssignment = taskAssignmentMapper.selectByPrimaryKey(taskId);
        if (taskAssignment == null) {
            // 判断任务流程是否存在
            throw new ServiceException(WorkerOrderConstant.ORDER_TASK_NOT_EXIST_ERROR);
        }
        /* 判断该任务流程是否已分配任务流程 [不需要该需求，所以去掉]
        if (taskAssignment.getTaskWorkerGroupId() != null) {
            throw new ServiceException(WorkerOrderConstant.TASK_IS_DISTRIBUTED_ERROR);
        }*/
        WorkerCaptain workerCaptain = workerGroupMapper.selectWorkerCaptainByGroupId(groupId);
        if (workerCaptain == null) {
            // 判断工人小组是否存在
            throw new ServiceException(WorkerOrderConstant.GROUP_IS_NOT_EXIST_ERROR);
        }
        if (workerCaptain.getProcessId() == null || !workerCaptain.getProcessId().equals(
                taskAssignment.getTaskProcessId()
        )) {
            // 判断工人小组是否和任务流程相匹配
            throw new ServiceException(WorkerOrderConstant.PROCESS_IS_NOT_MATCH_ERROR);
        }
        // 执行分配操作
        taskAssignment.setTaskWorkerGroupId(groupId);
        int result = taskAssignmentMapper.updateByPrimaryKeySelective(taskAssignment);
        if (result < 1) {
            throw new ServiceException(WorkerOrderConstant.SERVER_RUN_SQL_FAILURE,
                    WorkerOrderConstant.DISTRIBUTION_TASK_FAILURE);
        }
        /*
         * 提醒工人 [该需求取消]

        remindService.doRemind(
                new Remind(
                        workerCaptain.getUserId(), MessageFormatter.arrayFormat(
                        WorkerOrderConstant.REMIND_WORKER_TASK_TO_DO,
                        new String[]{taskAssignment.getTaskNo(),
                                taskAssignment.getTaskProcess().getProcessName()}
                ).getMessage(), taskAssignment.getTaskAssignmentId()
                ), Remind.TASK_REMIND_TYPE
        );*/
        /*
         * 当订单的第一优先级任务被分配后任务对应的订单状态变更为在库
         */
        // 获取订单的第一优先级任务
        String orderNo = taskAssignment.getTaskNo();
        TaskAssignment mostTask = taskAssignmentMapper.selectTheMostPriorityTask(orderNo);
        System.out.println("[this]" + JSON.toJSONString(taskAssignment));
        System.out.println("[this]" + JSON.toJSONString(mostTask));
        if (!taskAssignment.getTaskAssignmentId().equals(mostTask.getTaskAssignmentId())) {
            return;
        }
        // 若当前分配任务为第一优先级任务执行更新状态操作
        this.updateOrderStatus(orderNo, WorkOrder.IN_THE_LIBRARY_STATUS);
    }

    @Override
    public List<TaskAssignment> findLeaderTasks() {
        // 获取当前用户
        User currentUser = (User) userAuditor.getSession().getAttribute("userLogged");
        // 检查用户是否存在
        try {
            UserServiceImpl.checkUserProperties(currentUser, "userRole", "userId");
        } catch (AttributeCheckFailureException e) {
            if ("null".equals(e.getAttributeName())) {
                throw new ServiceException(UserConstant.NOT_LOGIN_ERROR);
            } else {
                throw e;
            }
        }
        // 判断用户是否是工人
        if (!"worker".equals(currentUser.getUserRole())) {
            throw new ServiceException(WorkerOrderConstant.FAIL_TO_FIND_TASKS_ERROR,
                    UserConstant.USER_IS_NOT_WORKER);
        }
        // 查询操作
        return taskAssignmentMapper.selectByLeaderId(
                currentUser.getUserId()
        );
    }

    @Override
    public void doFinishTask(Integer taskId, Integer groupId) {
        if (taskId == null) {
            throw new ServiceException(WorkerOrderConstant.TASK_ID_IS_REQUIRE_ERROR);
        }
        // 获取当前登录的用户
        User currentUser = userService.getLoggedUser();
        // 判断用户是否是工人
        if (!"worker".equals(currentUser.getUserRole())) {
            throw new ServiceException(WorkerOrderConstant.FAIL_TO_FIND_TASKS_ERROR,
                    UserConstant.USER_IS_NOT_WORKER);
        }
        // 判断用户是否是指定小组的工人组长
        WorkerCaptain leader = workerGroupMapper.selectWorkerCaptainByGroupId(groupId);
        if (leader == null || !currentUser.getUserId().equals(leader.getUserId())) {
            throw new ServiceException(WorkerOrderConstant.FAIL_TO_FINISH_TASK_ERROR,
                    UserConstant.USER_IS_NOT_LEADER);
        }
        // 获取指定小组的任务
        List<TaskAssignment> taskAssignments = taskAssignmentMapper.selectTasksByGroupId(groupId);
        if (taskAssignments.size() == 0) {
            throw new ServiceException(WorkerOrderConstant.TASKS_FOR_GROUP_IS_EMPTY_ERROR);
        }
        // 判断该任务是否可以完成
        for (int i = 0; i < taskAssignments.size(); i++) {
            TaskAssignment taskAssignment = taskAssignments.get(i);
            // 遍历中第一次遇到可完成的任务即当前小组可完成的任务
            if (taskAssignment.getPreDemandNum() == 0) {
                // 判断当前欲完成的任务是否和该任务是同一个bug
                if (!taskId.equals(taskAssignment.getTaskAssignmentId())) {
                    throw new ServiceException(WorkerOrderConstant.FAIL_TO_FINISH_TASK_ERROR,
                            WorkerOrderConstant.TASK_IS_NOT_EXPECTED);
                }
                this.finishTaskWithoutPermsCheck(taskId, taskAssignment.getTaskNo());
                if (taskAssignment.getTaskProcess().getProcessId() == 7) {
                    // 订单已打包完成操作
                    this.whileOrderFinish(taskAssignment.getTaskNo());
                } else if (taskAssignment.getTaskProcess().getProcessId() == 8) {
                    // 订单已发货操作
                    this.whileOrderSend(taskAssignment.getTaskNo());
                }
                return;
            }
        }
        throw new ServiceException(WorkerOrderConstant.FAIL_TO_FINISH_TASK_ERROR,
                WorkerOrderConstant.TASK_IS_NOT_EXPECTED);
    }

    /**
     * 当工单任务发货欲执行完成，工单状态因更新为已发，且需要客户为月结或付款状态为 清欠
     *
     * @param orderNo 工单号
     */
    private void whileOrderSend(String orderNo) {
        // 若果订单支付状态为未收且对应客户不是月结客户，则不能发货
        WorkOrder order = workOrderMapper.selectByOrderNo(orderNo);
        ObjectUtils.checkObjectProperties(order, WorkerOrderConstant.ORDER_NOT_EXIST_ERROR,
                "orderPaymentStatus", "orderCustomerId");
        if (order.getOrderPaymentStatus() != WorkOrder.PAID_STATUS) {
            if (!userService.hasRole(order.getOrderCustomerId(), "customer_special")) {
                throw new ServiceException(WorkerOrderConstant.WORK_CAN_NOT_SENDING_ERROR);
            }
        }
        this.updateOrderStatus(orderNo, WorkOrder.ENDED_STATUS);
    }

    /**
     * 私
     * 当订单流程更变为打包完成时，订单状态更改为完工
     *
     * @param orderNo 订单号
     */
    private void whileOrderFinish(String orderNo) {
        this.updateOrderStatus(orderNo, WorkOrder.COMPLETED_STATUS);
    }

    @Override
    public List<TaskAssignment> findPreTasks(Integer taskId) {
        return taskAssignmentMapper.selectPreTasks(taskId);
    }

    /**
     * 私有方法
     * 完成一个任务流程，并不检查权限
     *
     * @param taskId 任务id
     * @param taskNo 工单编号
     */
    private void finishTaskWithoutPermsCheck(Integer taskId, String taskNo) {
        TaskAssignment taskAssignment = taskAssignmentMapper.selectByPrimaryKey(taskId);
        if (taskAssignment.getTaskStatus() == TaskAssignment.TASK_FINISHED) {
            throw new ServiceException(WorkerOrderConstant.FAIL_TO_FINISH_TASK_ERROR,
                    WorkerOrderConstant.TASK_HAS_FINISHED);
        }
        // 更新操作
        TaskAssignment resultTask = new TaskAssignment();
        resultTask.setTaskAssignmentId(taskId);
        resultTask.setTaskStatus(TaskAssignment.TASK_FINISHED);
        int result = taskAssignmentMapper.updateByPrimaryKeySelective(resultTask);
        if (result < 1) {
            throw new ServiceException(WorkerOrderConstant.SERVER_RUN_SQL_FAILURE,
                    WorkerOrderConstant.FINISH_TASK_FAILURE);
        }
        // 获取所有属于该工单任务中任务未完成的工人团队队长
        List<WorkerGroup> leaderRecords = workerGroupMapper
                .selectWorkerCaptainGroupsUnFinishInOrder(taskNo);
        if (leaderRecords == null || leaderRecords.size() == 0) {
            logger.info("所有任务已完成！");
            return;
        }
        User leader = leaderRecords.get(0).getWorker();
        remindService.doRemind(
                new Remind(
                        leader.getUserId(), MessageFormatter.arrayFormat(
                        WorkerOrderConstant.REMIND_TASK_CAN_BE_FINISH,
                        new String[]{taskAssignment.getTaskNo(),
                                taskAssignment.getTaskProcess().getProcessName()}
                ).getMessage()
                ), Remind.NORMAL_TYPE
        );
    }

    /**
     * 私
     * 更新工单状态
     *
     * @param orderNo 工单编号
     * @param status  欲更新的状态
     */
    private void updateOrderStatus(String orderNo, Integer status) {
        // 更新订单状态
        WorkOrder workOrder = new WorkOrder();
        workOrder.setOrderTaskNo(orderNo);
        workOrder.setOrderStatus(status);
        if (status == WorkOrder.ENDED_STATUS) {
            workOrder.setOrderFinishTime(new Date());
        }
        int result1 = workOrderMapper.updateOrderStatus(workOrder);
        if (result1 < 1) {
            throw new ServiceException(WorkerOrderConstant.SERVER_RUN_SQL_FAILURE,
                    WorkerOrderConstant.DISTRIBUTION_TASK_FAILURE);
        }
        /*
         * 提醒用户及管理
         */
        // 获取订单对应的实体
        WorkOrder order = workOrderMapper.selectByOrderNo(orderNo);
        if (order != null) {
            // 获取当前状态
            String message;
            switch (order.getOrderStatus()) {
                case WorkOrder.IN_THE_LIBRARY_STATUS:
                    message = "在库";
                    break;
                case WorkOrder.COMPLETED_STATUS:
                    message = "完工";
                    break;
                case WorkOrder.SHIPPED_STATUS:
                    message = "已发";
                    break;
                case WorkOrder.ENDED_STATUS:
                    message = "已完成";
                    break;
                default:
                    message = "未知状态";
            }
            // 提醒客户
            remindService.doRemind(
                    new Remind(
                            order.getOrderCustomerId(), MessageFormatter.arrayFormat(
                            WorkerOrderConstant.REMIND_CUSTOMER_ORDER_UPDATE,
                            new String[]{order.getOrderNumber(), message}
                    ).getMessage(), order.getOrderId()
                    ), Remind.ORDER_REMIND_TYPE
            );
            // 销售管理提醒
            remindService.doRemind(
                    new Remind(
                            order.getOrderChargeManagerId(), MessageFormatter.arrayFormat(
                            WorkerOrderConstant.REMIND_MANAGER_ORDER_UPDATE,
                            new String[]{order.getOrderNumber(), message}
                    ).getMessage(), order.getOrderId()
                    ), Remind.ORDER_REMIND_TYPE
            );
        }
    }
}
